<!DOCTYPE html>
<html lang="en">
    <head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="format-detection" content="telephone=no" />

  <title>
    34|关于 Linux 网络，你必须知道这些（下） | 迪克猪的博客
  </title>

  
  <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
  <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
  <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
  <link rel="manifest" href="/manifest.json" />
  <meta name="theme-color" content="#ffffff" />

  
  <link
    rel="stylesheet"
    href="https://unpkg.com/modern-normalize@0.6.0/modern-normalize.css"
  />

  
  
  
  
  <link rel="stylesheet" href="https://zsy619.github.io/style.min.f7761d111b74dd5c07f0111decee92938c12abc42e0fd319e1a07483e248b54e.css" integrity="sha256-93YdERt03VwH8BEd7O6Sk4wSq8QuD9MZ4aB0g&#43;JItU4=" />

  
  
    
  
</head>

    <body>
        <header id="header">
  <div class="header_container">
    <h1 class="sitetitle">
      <a href="https://zsy619.github.io" title="迪克猪的博客">迪克猪的博客</a>
    </h1>
    <nav class="navbar">
      <ul>
        <li><a href="https://zsy619.github.io">Home</a></li>
        
          <li>
            <a href="/post/">
              
              <span>LINUX性能优化</span>
            </a>
          </li>
        
          <li>
            <a href="/csapp/">
              
              <span>深入理解计算机系统_第三版</span>
            </a>
          </li>
        
          <li>
            <a href="/golang/">
              
              <span>golang</span>
            </a>
          </li>
        
          <li>
            <a href="/docker/">
              
              <span>容器</span>
            </a>
          </li>
        
          <li>
            <a href="/flutter/">
              
              <span>Flutter</span>
            </a>
          </li>
        
          <li>
            <a href="/know/">
              
              <span>知识点</span>
            </a>
          </li>
        
          <li>
            <a href="/categories/">
              
              <span>目录</span>
            </a>
          </li>
        
          <li>
            <a href="/about/">
              
              <span>关于</span>
            </a>
          </li>
        
        <li class="hide-sm"><a href="https://zsy619.github.io/index.xml" type="application/rss+xml">RSS</a></li>
      </ul>
    </nav>
  </div>
</header>

        
<section id="main">
  <article class="post content">
    <h2 class="title">34|关于 Linux 网络，你必须知道这些（下）</h2>
    <div class="post_content">
      <h3 id="性能指标">性能指标</h3>
<p>通常用带宽、吞吐量、延时、PPS（Packet Per Second）等指标衡量网络的性能。</p>
<ul>
<li>带宽，表示链路的最大传输速率，单位通常为 b/s （比特 / 秒）。</li>
<li>吞吐量，表示单位时间内成功传输的数据量，单位通常为 b/s（比特 / 秒）或者 B/s（字节 / 秒）。吞吐量受带宽限制，而吞吐量 / 带宽，也就是该网络的使用率。</li>
<li>延时，表示从网络请求发出后，一直到收到远端响应，所需要的时间延迟。在不同场景中，这一指标可能会有不同含义。比如，它可以表示，建立连接需要的时间（比如 TCP 握手延时），或一个数据包往返所需的时间（比如 RTT）。</li>
<li>PPS，是 Packet Per Second（包 / 秒）的缩写，表示以网络包为单位的传输速率。PPS 通常用来评估网络的转发能力，比如硬件交换机，通常可以达到线性转发（即 PPS 可以达到或者接近理论最大值）。而基于 Linux 服务器的转发，则容易受网络包大小的影响。</li>
</ul>
<p>除了这些指标，网络的可用性（网络能否正常通信）、并发连接数（TCP 连接数量）、丢包率（丢包百分比）、重传率（重新传输的网络包比例）等也是常用的性能指标。</p>
<h3 id="网络配置">网络配置</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">ifconfig 和 ip 分别属于软件包 net-tools 和 iproute2，iproute2 是 net-tools 的下一代。通常情况下它们会在发行版中默认安装。但如果你找不到 ifconfig 或者 ip 命令，可以安装这两个软件包。
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ ifconfig en0                                                                                                           
en0: flags<span style="color:#f92672">=</span>8823&lt;UP,BROADCAST,SMART,SIMPLEX,MULTICAST&gt; mtu <span style="color:#ae81ff">1500</span>
	options<span style="color:#f92672">=</span>400&lt;CHANNEL_IO&gt;
	ether 78:4f:43:68:02:c6
	nd6 options<span style="color:#f92672">=</span>201&lt;PERFORMNUD,DAD&gt;
	media: autoselect <span style="color:#f92672">(</span>&lt;unknown type&gt;<span style="color:#f92672">)</span>
	status: inactive
</code></pre></div><p>ip -s addr show dev eth0</p>
<p>ifconfig 和 ip 命令输出的指标基本相同，只是显示格式略微不同。比如，它们都包括了网络接口的状态标志、MTU 大小、IP、子网、MAC 地址以及网络包收发的统计信息。</p>
<p>第一，网络接口的状态标志。ifconfig 输出中的 RUNNING ，或 ip 输出中的 LOWER_UP ，都表示物理网络是连通的，即网卡已经连接到了交换机或者路由器中。如果你看不到它们，通常表示网线被拔掉了。</p>
<p>第二，MTU 的大小。MTU 默认大小是 1500，根据网络架构的不同（比如是否使用了 VXLAN 等叠加网络），你可能需要调大或者调小 MTU 的数值。</p>
<p>第三，网络接口的 IP 地址、子网以及 MAC 地址。这些都是保障网络功能正常工作所必需的，你需要确保配置正确。</p>
<p>第四，网络收发的字节数、包数、错误数以及丢包情况，特别是 TX 和 RX 部分的 errors、dropped、overruns、carrier 以及 collisions 等指标不为 0 时，通常表示出现了网络 I/O 问题。其中：</p>
<ul>
<li>errors 表示发生错误的数据包数，比如校验错误、帧同步错误等；</li>
<li>dropped 表示丢弃的数据包数，即数据包已经收到了 Ring Buffer，但因为内存不足等原因丢包；</li>
<li>overruns 表示超限数据包数，即网络 I/O 速度过快，导致 Ring Buffer 中的数据包来不及处理（队列满）而导致的丢包；</li>
<li>carrier 表示发生 carrirer 错误的数据包数，比如双工模式不匹配、物理电缆出现问题等；</li>
<li>collisions 表示碰撞数据包数。</li>
</ul>
<h3 id="套接字信息">套接字信息</h3>
<p>ifconfig 和 ip 只显示了网络接口收发数据包的统计信息，但在实际的性能问题中，网络协议栈中的统计信息，我们也必须关注。你可以用 netstat 或者 ss ，来查看套接字、网络栈、网络接口以及路由表的信息。</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">
<span style="color:#75715e"># head -n 3 表示只显示前面3行</span>
<span style="color:#75715e"># -l 表示只显示监听套接字</span>
<span style="color:#75715e"># -n 表示显示数字地址和端口(而不是名字)</span>
<span style="color:#75715e"># -p 表示显示进程信息</span>
$ netstat -nlp | head -n <span style="color:#ae81ff">3</span>
Active Internet connections <span style="color:#f92672">(</span>only servers<span style="color:#f92672">)</span>
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        <span style="color:#ae81ff">0</span>      <span style="color:#ae81ff">0</span> 127.0.0.53:53           0.0.0.0:*               LISTEN      840/systemd-resolve

<span style="color:#75715e"># -l 表示只显示监听套接字</span>
<span style="color:#75715e"># -t 表示只显示 TCP 套接字</span>
<span style="color:#75715e"># -n 表示显示数字地址和端口(而不是名字)</span>
<span style="color:#75715e"># -p 表示显示进程信息</span>
$ ss -ltnp | head -n <span style="color:#ae81ff">3</span>
State    Recv-Q    Send-Q        Local Address:Port        Peer Address:Port
LISTEN   <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">128</span>           127.0.0.53%lo:53               0.0.0.0:*        users:<span style="color:#f92672">((</span><span style="color:#e6db74">&#34;systemd-resolve&#34;</span>,pid<span style="color:#f92672">=</span>840,fd<span style="color:#f92672">=</span>13<span style="color:#f92672">))</span>
LISTEN   <span style="color:#ae81ff">0</span>         <span style="color:#ae81ff">128</span>                 0.0.0.0:22               0.0.0.0:*        users:<span style="color:#f92672">((</span><span style="color:#e6db74">&#34;sshd&#34;</span>,pid<span style="color:#f92672">=</span>1459,fd<span style="color:#f92672">=</span>3<span style="color:#f92672">))</span>
</code></pre></div><p>其中，接收队列（Recv-Q）和发送队列（Send-Q）需要你特别关注，它们通常应该是 0。当你发现它们不是 0 时，说明有网络包的堆积发生。</p>
<p>当然还要注意，在不同套接字状态下，它们的含义不同。当套接字处于连接状态（Established）时，</p>
<ul>
<li>Recv-Q 表示套接字缓冲还没有被应用程序取走的字节数（即接收队列长度）。</li>
<li>而 Send-Q 表示还没有被远端主机确认的字节数（即发送队列长度）。</li>
</ul>
<p>当套接字处于监听状态（Listening）时，</p>
<ul>
<li>Recv-Q 表示全连接队列的长度。</li>
<li>而 Send-Q 表示全连接队列的最大长度。</li>
</ul>
<p>所谓全连接，是指服务器收到了客户端的 ACK，完成了 TCP 三次握手，然后就会把这个连接挪到全连接队列中。这些全连接中的套接字，还需要被 accept() 系统调用取走，服务器才可以开始真正处理客户端的请求。</p>
<p>与全连接队列相对应的，还有一个半连接队列。所谓半连接是指还没有完成 TCP 三次握手的连接，连接只进行了一半。服务器收到了客户端的 SYN 包后，就会把这个连接放到半连接队列中，然后再向客户端发送 SYN+ACK 包。</p>
<h3 id="协议栈统计信息">协议栈统计信息</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">
$ netstat -s
...
Tcp:
    <span style="color:#ae81ff">3244906</span> active connection openings
    <span style="color:#ae81ff">23143</span> passive connection openings
    <span style="color:#ae81ff">115732</span> failed connection attempts
    <span style="color:#ae81ff">2964</span> connection resets received
    <span style="color:#ae81ff">1</span> connections established
    <span style="color:#ae81ff">13025010</span> segments received
    <span style="color:#ae81ff">17606946</span> segments sent out
    <span style="color:#ae81ff">44438</span> segments retransmitted
    <span style="color:#ae81ff">42</span> bad segments received
    <span style="color:#ae81ff">5315</span> resets sent
    InCsumErrors: <span style="color:#ae81ff">42</span>
...

$ ss -s
Total: <span style="color:#ae81ff">186</span> <span style="color:#f92672">(</span>kernel 1446<span style="color:#f92672">)</span>
TCP:   <span style="color:#ae81ff">4</span> <span style="color:#f92672">(</span>estab 1, closed 0, orphaned 0, synrecv 0, timewait 0/0<span style="color:#f92672">)</span>, ports <span style="color:#ae81ff">0</span>

Transport Total     IP        IPv6
*    <span style="color:#ae81ff">1446</span>      -         -
RAW    <span style="color:#ae81ff">2</span>         <span style="color:#ae81ff">1</span>         <span style="color:#ae81ff">1</span>
UDP    <span style="color:#ae81ff">2</span>         <span style="color:#ae81ff">2</span>         <span style="color:#ae81ff">0</span>
TCP    <span style="color:#ae81ff">4</span>         <span style="color:#ae81ff">3</span>         <span style="color:#ae81ff">1</span>
...
</code></pre></div><p>这些协议栈的统计信息都很直观。ss 只显示已经连接、关闭、孤儿套接字等简要统计，而 netstat 则提供的是更详细的网络协议栈信息。</p>
<h3 id="网络吞吐和-pps">网络吞吐和 PPS</h3>
<p>给 sar 增加 -n 参数就可以查看网络的统计信息，比如网络接口（DEV）、网络接口错误（EDEV）、TCP、UDP、ICMP 等等。执行下面的命令，你就可以得到网络接口统计信息：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">
<span style="color:#75715e"># 数字1表示每隔1秒输出一组数据</span>
$ sar -n DEV <span style="color:#ae81ff">1</span>
Linux 4.15.0-1035-azure <span style="color:#f92672">(</span>ubuntu<span style="color:#f92672">)</span>   01/06/19   _x86_64_  <span style="color:#f92672">(</span><span style="color:#ae81ff">2</span> CPU<span style="color:#f92672">)</span>

13:21:40        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
13:21:41         eth0     18.00     20.00      5.79      4.25      0.00      0.00      0.00      0.00
13:21:41      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
13:21:41           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
</code></pre></div><p>这儿输出的指标比较多，我来简单解释下它们的含义。</p>
<ul>
<li>rxpck/s 和 txpck/s 分别是接收和发送的 PPS，单位为包 / 秒。</li>
<li>rxkB/s 和 txkB/s 分别是接收和发送的吞吐量，单位是 KB/ 秒。</li>
<li>rxcmp/s 和 txcmp/s 分别是接收和发送的压缩数据包数，单位是包 / 秒。</li>
<li>%ifutil 是网络接口的使用率，即半双工模式下为 (rxkB/s+txkB/s)/Bandwidth，而全双工模式下为 max(rxkB/s, txkB/s)/Bandwidth。</li>
</ul>
<p>其中，Bandwidth 可以用 ethtool 来查询，它的单位通常是 Gb/s 或者 Mb/s，不过注意这里小写字母 b ，表示比特而不是字节。我们通常提到的千兆网卡、万兆网卡等，单位也都是比特。</p>
<h3 id="连通性和延时">连通性和延时</h3>
<p>通常使用 ping ，来测试远程主机的连通性和延时，而这基于 ICMP 协议。比如，执行下面的命令，你就可以测试本机到 114.114.114.114 这个 IP 地址的连通性和延时：</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">
<span style="color:#75715e"># -c3表示发送三次ICMP包后停止</span>
$ ping -c3 114.114.114.114
PING 114.114.114.114 <span style="color:#f92672">(</span>114.114.114.114<span style="color:#f92672">)</span> 56<span style="color:#f92672">(</span>84<span style="color:#f92672">)</span> bytes of data.
<span style="color:#ae81ff">64</span> bytes from 114.114.114.114: icmp_seq<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span> ttl<span style="color:#f92672">=</span><span style="color:#ae81ff">54</span> time<span style="color:#f92672">=</span><span style="color:#ae81ff">244</span> ms
<span style="color:#ae81ff">64</span> bytes from 114.114.114.114: icmp_seq<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span> ttl<span style="color:#f92672">=</span><span style="color:#ae81ff">47</span> time<span style="color:#f92672">=</span><span style="color:#ae81ff">244</span> ms
<span style="color:#ae81ff">64</span> bytes from 114.114.114.114: icmp_seq<span style="color:#f92672">=</span><span style="color:#ae81ff">3</span> ttl<span style="color:#f92672">=</span><span style="color:#ae81ff">67</span> time<span style="color:#f92672">=</span><span style="color:#ae81ff">244</span> ms

--- 114.114.114.114 ping statistics ---
<span style="color:#ae81ff">3</span> packets transmitted, <span style="color:#ae81ff">3</span> received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev <span style="color:#f92672">=</span> 244.023/244.070/244.105/0.034 ms
</code></pre></div><p>ping 的输出，可以分为两部分。</p>
<ul>
<li>第一部分，是每个 ICMP 请求的信息，包括 ICMP 序列号（icmp_seq）、TTL（生存时间，或者跳数）以及往返延时。</li>
<li>第二部分，则是三次 ICMP 请求的汇总。</li>
</ul>
<h3 id="小结">小结</h3>
<p>我们通常使用带宽、吞吐量、延时等指标，来衡量网络的性能；相应的，你可以用 ifconfig、netstat、ss、sar、ping 等工具，来查看这些网络的性能指标。</p>

    </div>
    <div class="info post_meta">
      <time datetime=2020-05-31T17:16:28&#43;0800 class="date">Sunday, May 31, 2020</time>
      
        <ul class="tags">
        
          <li> <a href="https://zsy619.github.io/tags/linux%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96">linux性能优化</a> </li>
        
          <li> <a href="https://zsy619.github.io/tags/linux">linux</a> </li>
        
        </ul>
      
      
    </div>
    <div class="clearfix"></div>
  </article>
  
    <div class="other_posts">
      
      <a href="https://zsy619.github.io/post/35%E5%9F%BA%E7%A1%80%E7%AF%87c10k-%E5%92%8C-c1000k-%E5%9B%9E%E9%A1%BE/" class="prev">35|基础篇：C10K 和 C1000K 回顾</a>
      
      
      <a href="https://zsy619.github.io/post/33%E5%85%B3%E4%BA%8E-linux-%E7%BD%91%E7%BB%9C%E4%BD%A0%E5%BF%85%E9%A1%BB%E7%9F%A5%E9%81%93%E8%BF%99%E4%BA%9B%E4%B8%8A/" class="next">33|关于 Linux 网络，你必须知道这些（上）</a>
      
    </div>
    <aside id="comments">
</aside>

  
</section>

        <a id="back_to_top" title="Go To Top" href="#">
  <span>
    <svg viewBox="0 0 24 24">
      <path fill="none" d="M0 0h24v24H0z"></path>
      <path d="M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71z"></path>
    </svg>
  </span>
</a>

        <footer id="footer">
  <p>
    <span>&copy; 2021 <a href="https://zsy619.github.io" title="迪克猪的博客">迪克猪的博客</a> </span>
    <span>Built with <a rel="nofollow" target="_blank" href="https://gohugo.io">Hugo</a></span>
    <span>Theme by <a rel="nofollow" target="_blank" href="https://github.com/wayjam/hugo-theme-mixedpaper">WayJam</a></span>
  </p>

  <script src="https://zsy619.github.io/js/main.min.8b182175f5874aeed0acc0979345c98d4bde22208ec4f36cc1d6e3102acb4b10.js" integrity="sha256-ixghdfWHSu7QrMCXk0XJjUveIiCOxPNswdbjECrLSxA=" crossorigin="anonymous" async></script>
</footer>

    </body>
</html>
